// JWT 验证中间件

import { NextFunction, Request, Response } from 'express';
import jwt from 'jsonwebtoken';
import { config } from '../config';
import Log from '../utils/log';
import dayjs from 'dayjs';

// 白名单中的URL
const whiteList = ['/user/register', '/user/login'];

const authenticateToken = (req: Request, res: Response, next: NextFunction) => {
  Log.info('-------------------------------------------');
  // const fullUrl = `${req.protocol}://${req.get('host')}:${req.originalUrl}`;
  // console.log(colors('cyan', `接收到来自该地址的请求: ${fullUrl}`));
  Log.info(`来自客户端的数据：${dayjs().format('YYYY-MM-DD HH:mm:ss')} >>> ${JSON.stringify(req.getParams())}`);
  Log.info('\n');

  // 如果请求的URL是白名单中的URL之一，则跳过验证
  if (whiteList.some((i) => req.originalUrl.startsWith(i))) {
    Log.warn(`此跳过验证：${req.originalUrl}`);
    next();
    return;
  }

  // 检查请求头中是否包含'authorization'字段
  const authHeader = req.headers['authorization'];
  // 从请求头中获取'authorization'字段
  const token = authHeader && authHeader.split(' ')[0];
  // 如果没有token，则返回401
  if (token == null) {
    Log.error(`没有token: ${req.originalUrl}`);
    return res.sendStatus(401);
  }

  // 服务端能够自己解析出令牌是否会过期，前后端都不需要额外的操作
  jwt.verify(token, config.jwtSecret, (err, decoded) => {
    // 如果token验证失败，则返回403
    if (err) {
      Log.error(`token验证失败: ${req.originalUrl}`);
      return res.sendStatus(401);
    }
    if (decoded && typeof decoded == 'object' && decoded.userId) {
      req.userId = decoded.userId; // 将用户ID存储在请求对象中
    }
    Log.info(`认证成功: ${req.originalUrl}`);
    next();
  });
};

export default authenticateToken;
